package edu.mse.camel.client.whiteboard.gef.ui.editpart;

import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Polyline;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.NodeEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;

import edu.mse.camel.client.whiteboard.gef.ui.WhiteBoardUtil;
import edu.mse.camel.client.whiteboard.gef.whiteboard.FreeWritingShape;
import edu.mse.camel.client.whiteboard.gef.whiteboard.XY;

/**
 * EditPart used for Shape instances (more specific for EllipticalShape and
 * RectangularShape instances).
 * <p>
 * This edit part must implement the PropertyChangeListener interface, so it can
 * be notified of property changes in the corresponding model element.
 * </p>
 * 
 * @author Elias Volanakis
 */
public class FreeWritingShapeEditPart extends AbstractGraphicalEditPart
implements Adapter, NodeEditPart, IWhiteboardEditPart {

	public AbstractGraphicalEditPart getEditPart() {
		return this;
	}

	public FreeWritingShapeEditPart(Object model) {
		this.setModel(model);
	}

	/**
	 * Upon activation, attach to the model element as a property change
	 * listener.
	 */
	public void activate() {
		if (!isActive()) {
			super.activate();
			((Notifier) getModel()).eAdapters().add(this);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.gef.editparts.AbstractEditPart#createEditPolicies()
	 */
	protected void createEditPolicies() {
		installEditPolicy(EditPolicy.COMPONENT_ROLE,
				new FreeWritingShapeComponentEditPolicy());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure()
	 */
	protected IFigure createFigure() {
		return createFigureForModel();

	}

	private IFigure createFigureForModel() {
		FreeWritingShape shape = getCastedModel();
		
		Polyline line = new Polyline();
		Point loc = shape.getLocation();
		
		PointList pList = new PointList();
		for (XY xy : shape.getPoints()) {
			Point p = new Point(xy.getX() + loc.x, xy.getY() + loc.y);
			pList.addPoint(p);
		}
		line.setPoints(pList);
		line.setForegroundColor(
				WhiteBoardUtil.createColorFromRGB(getCastedModel().getColor()));
		line.setLineWidth(WhiteBoardUtil.FIGURE_WIDTH);
		return line;

	}

	/**
	 * Upon deactivation, detach from the model element as a property change
	 * listener.
	 */
	public void deactivate() {
		if (isActive()) {
			super.deactivate();
			((Notifier) getModel()).eAdapters().remove(this);
		}
	}

	private FreeWritingShape getCastedModel() {
		return (FreeWritingShape) getModel();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.NodeEditPart#getSourceConnectionAnchor(org.eclipse.gef
	 * .ConnectionEditPart)
	 */
	public ConnectionAnchor getSourceConnectionAnchor(
			ConnectionEditPart connection) {
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.NodeEditPart#getSourceConnectionAnchor(org.eclipse.gef
	 * .Request)
	 */
	public ConnectionAnchor getSourceConnectionAnchor(Request request) {
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.NodeEditPart#getTargetConnectionAnchor(org.eclipse.gef
	 * .ConnectionEditPart)
	 */
	public ConnectionAnchor getTargetConnectionAnchor(
			ConnectionEditPart connection) {
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.NodeEditPart#getTargetConnectionAnchor(org.eclipse.gef
	 * .Request)
	 */
	public ConnectionAnchor getTargetConnectionAnchor(Request request) {
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seejava.beans.PropertyChangeListener#propertyChange(java.beans.
	 * PropertyChangeEvent)
	 */

	public Notifier getTarget() {
		return (Notifier) getModel();
	}

	public void setTarget(Notifier notifier) {

	}

	public boolean isAdapterForType(Object object) {
		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seejava.beans.PropertyChangeListener#propertyChange(java.beans.
	 * PropertyChangeEvent)
	 */
	public void notifyChanged(Notification notification) {
		refresh();
	}

	protected void refreshVisuals() {
		// notify parent container of changed position & location
		// if this line is removed, the XYLayoutManager used by the parent
		// container
		// (the Figure of the ShapesDiagramEditPart), will not know the bounds
		// of this figure
		// and will not draw it correctly.
		Rectangle bounds = new Rectangle(getCastedModel().getLocation(),
				getCastedModel().getSize());
		
		Polyline line = (Polyline) getFigure();
		Point loc = getCastedModel().getLocation();
		
		PointList pList = new PointList();
		for (XY xy : getCastedModel().getPoints()) {
			Point p = new Point(xy.getX() + loc.x, xy.getY() + loc.y);
			pList.addPoint(p);
		}
		line.setPoints(pList);
		
		if (getParent() != null)
			((GraphicalEditPart) getParent()).setLayoutConstraint(this,
					getFigure(), bounds);

	}
}
